package com.daily.pump.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.OvershootInterpolator;

import androidx.annotation.Nullable;

import com.xunxi.mimi.utils.ScreenUtils;


/**
 * Created by liyu on 17/8/3.
 */
public class CompressView extends View {

    public static final int DELAY_TIME = 50;
    private Paint paint, tmpPaint, textPaint, strokePain;
    private RectF rect;
    private int backGroundColor;    //背景色
    private float pointLength;      //指针长度
    private float per;             //指数百分比
    private float destPer;        //目标位置
    private float perPoint;        //缓存(变化中)指针百分比
    private float length;          //仪表盘半径
    private float r;

    private float mLastX;
    private float dx;

    private int mWidth, mHeight;

    private int color_393939, color_636363, color_D5ECFC, color_ACCEE9, color_1aACCEE9, color_0CB982;

    private int ring_bg, ring_second_bg, color_ring_bg, color_disable_ring_bg;
    /**
     * 处理多点触控的情况，准确地计算Y坐标和移动距离dy
     * 同时兼容单点触控的情况
     */
    private int mActivePointerId = MotionEvent.INVALID_POINTER_ID;

    /**
     * 是否正在触碰
     */
    private boolean isTouching;

    private float rotate = 1;

    private boolean isDrawerLine;

    private SweepGradient rotateGradient;

    private boolean mEnableTouch;

    private boolean mIsMaxAspect;

    private Handler mHandler = new Handler();

    public CompressView(Context context) {
        super(context);
        init();
    }

    public CompressView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeight = mWidth;
        initIndex(mWidth / 2);
        //优化组件高度
        setMeasuredDimension(mWidth, mHeight);
    }

    /**
     * Desc:设置是否可用,不可用置灰
     * <p>
     * Author: [李豫]
     * Date: 2020-10-24
     *
     * @param enable
     */
    public void setEnableCompress(boolean enable) {
        this.mEnableTouch = enable;
        if (mEnableTouch) {
            ring_bg = color_ring_bg;
            ring_second_bg = color_D5ECFC;
        } else {
            ring_bg = color_disable_ring_bg;
            ring_second_bg = color_disable_ring_bg;
        }
        invalidate();
    }

    public boolean isEnableTouch() {
        return mEnableTouch;
    }

    private void initIndex(int specSize) {
        backGroundColor = Color.parseColor("#979498");
        r = specSize;
        if (mIsMaxAspect) {
            length = r / 5 * 4;
            pointLength = -(float) (r * 0.68);
        } else {
            length = r / 3 * 2;
            pointLength = -(float) (r * 0.55);
        }
    }

    private void init() {
        paint = new Paint();
        rect = new RectF();
        textPaint = new Paint();
        tmpPaint = new Paint();
        strokePain = new Paint();

        color_393939 = Color.parseColor("#393939");
        color_636363 = Color.parseColor("#636363");
        color_D5ECFC = Color.parseColor("#84D7F3");
        color_ACCEE9 = Color.parseColor("#D7EAF9");
        color_1aACCEE9 = Color.parseColor("#ACCEE9");
        color_0CB982 = Color.parseColor("#0CB982");

        color_ring_bg = Color.parseColor("#4E909D");
        color_disable_ring_bg = Color.parseColor("#676566");
        ring_bg = color_disable_ring_bg;
        ring_second_bg = color_disable_ring_bg;

        int[] colors = {color_disable_ring_bg, color_disable_ring_bg};
        float[] positions = {0.1f, 0.9f};
        rotateGradient = new SweepGradient(0, 0, colors, positions);

        mIsMaxAspect = ScreenUtils.getScreenHeight(getContext()) / (float) ScreenUtils.getScreenWidth(getContext()) > 1.87;
    }

    public CompressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public void setR(float r) {
        this.r = r;
        this.length = r / 4 * 3;
    }

    @Override
    protected void onDraw(Canvas canvas) {

//        setLayerType(LAYER_TYPE_SOFTWARE, null);
        //颜色指示的环
        initRing(canvas);
        //刻度文字
//        initScale(canvas);
        //提示内容
//        initText(canvas);
    }

    private void initText(Canvas canvas) {
        //抗锯齿
        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
        canvas.restore();
        canvas.save();
        canvas.translate(canvas.getWidth() / 2, r);

        float rIndex = length;

        //设置文字展示的圆环
        paint.setColor(Color.parseColor("#eeeeee"));
        paint.setShader(null);
        paint.setShadowLayer(5, 0, 0, 0x54000000);
        rect = new RectF(-(rIndex / 3), -(rIndex / 3), rIndex / 3, rIndex / 3);
        canvas.drawArc(rect, 0, 360, true, paint);

        paint.clearShadowLayer();

        canvas.restore();
        canvas.save();
        canvas.translate(canvas.getWidth() / 2f, r);

        textPaint.setStrokeWidth(1);
        textPaint.setAntiAlias(true);

        textPaint.setTextSize(60);
        textPaint.setColor(Color.parseColor("#fc6555"));
        textPaint.setTextAlign(Paint.Align.RIGHT);

        //判断指数变化及颜色设定

        int _per = (int) (per * 120);

        if (_per < 60) {
            textPaint.setColor(Color.parseColor("#ff6450"));
        } else if (_per < 100) {
            textPaint.setColor(Color.parseColor("#f5a623"));
        } else {
            textPaint.setColor(Color.parseColor("#79d062"));
        }

        float swidth = textPaint.measureText(String.valueOf(_per));
        //计算偏移量 是的数字和百分号整体居中显示
        swidth = (swidth - (swidth + 22) / 2);


        canvas.translate(swidth, 0);
        canvas.drawText("" + _per, 0, 0, textPaint);

        textPaint.setTextSize(30);
        textPaint.setTextAlign(Paint.Align.LEFT);

        canvas.drawText("%", 0, 0, textPaint);
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setColor(Color.parseColor("#999999"));


        canvas.restore();
        canvas.save();
        canvas.translate(canvas.getWidth() / 2, r + length / 3 / 2);
        canvas.drawText("完成率", 0, 0, textPaint);
    }

    public void setBackGroundColor(int color) {
        this.backGroundColor = color;
    }

    public void setPointLength1(float pointLength1) {
        this.pointLength = -length * pointLength1;
    }

    private void initScale(Canvas canvas) {
        canvas.restore();
        canvas.save();
        canvas.translate(canvas.getWidth() / 2, r);
        paint.setColor(Color.parseColor("#999999"));

        tmpPaint = new Paint(paint); //小刻度画笔对象
        tmpPaint.setStrokeWidth(1);
        tmpPaint.setTextSize(35);
        tmpPaint.setTextAlign(Paint.Align.CENTER);

        canvas.rotate(-90, 0f, 0f);

        float y = length;
        y = -y;
        int count = 12; //总刻度数
        paint.setColor(backGroundColor);

        float tempRou = 180 / 12f;

        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(5);

        //绘制刻度和百分比
        for (int i = 0; i <= count; i++) {

            if (i % 2 == 0) {
                canvas.drawText(String.valueOf((i) * 10), 0, y - 20f, tmpPaint);
            }

            canvas.drawLine(0f, y, 0, y + length / 15, paint);


            canvas.rotate(tempRou, 0f, 0f);
        }

    }

    //#197E5C
    private void initPointer(Canvas canvas) {

        //绘制指针
        paint.setColor(Color.WHITE);

        canvas.restore();
        canvas.save();
        canvas.translate(canvas.getWidth() / 2, r);
        float change;

        if (perPoint > 1) {
            perPoint = 1;
        } else if (perPoint < 0) {
            perPoint = 0;
        }
        change = perPoint * 260;

        if (mCompressViewListener != null) {
            mCompressViewListener.getCompressValue(perPoint);
        }
        //根据参数得到旋转角度
        canvas.rotate(-130 + change, 0f, 0f);

        //绘制三角形形成指针
        Path path = new Path();
        path.moveTo(0, pointLength);
        path.lineTo(-25, 0);
        path.lineTo(25, 0);
        path.lineTo(0, pointLength);
        path.close();

        canvas.drawPath(path, paint);
    }

    /**
     * Desc:绘制刻度线
     * <p>
     * Author: [李豫]
     * Date: 2020-08-26
     */
    private void initMarkLine(Canvas canvas) {
        //绘制刻度线
        paint.setColor(color_0CB982);
        canvas.restore();
        canvas.save();
        canvas.translate(canvas.getWidth() / 2, r);

        float lineChange;
        if (destPer < 1) {
            lineChange = destPer * 260;
        } else {
            lineChange = 260;
        }
        canvas.rotate(-130 + lineChange, 0f, 0f);

        //绘制压力刻度线
//        Path linePath = new Path();
//        linePath.moveTo(length, 0);
//        linePath.lineTo(length, 3);
//        linePath.lineTo(0, 3);
//        linePath.lineTo(0, 0);
//        linePath.close();
        Path linePath = new Path();
        linePath.moveTo(0, pointLength);
        linePath.lineTo(-5, 0);
        linePath.lineTo(5, 0);
        linePath.lineTo(5, pointLength);
        linePath.lineTo(-5, pointLength);

        linePath.close();
        canvas.drawPath(linePath, paint);
    }

    //#3D494A
    private void initRing(Canvas canvas) {
        paint.setAntiAlias(true);
        paint.setStrokeWidth(2);
        canvas.save();
        canvas.translate(canvas.getWidth() / 2, r);

        //前100红黄渐变圆环
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(ring_bg);
        rect = getRectF(-length, -length, length, length);
        canvas.drawArc(rect, 135, 270, true, paint);

        paint.setColor(color_393939);
        paint.setShader(null);
        rect = getRectF(-0.98f * length, -(length * 0.98f), 0.98f * length, 0.98f * length);
        canvas.drawArc(rect, 135, 270, true, paint);

        paint.setColor(ring_bg);
        paint.setShader(null);
        rect = getRectF(-0.96f * length, -(length * 0.96f), 0.96f * length, 0.96f * length);
        canvas.drawArc(rect, 135, 270, true, paint);

        paint.setColor(Color.WHITE);
        paint.setShader(null);
        rect = getRectF(-0.86f * length, -(length * 0.86f), 0.86f * length, 0.86f * length);
        canvas.drawArc(rect, 140, 260, true, paint);

        paint.setColor(ring_bg);
        paint.setShader(null);
        rect = getRectF(-0.84f * length, -(length * 0.84f), 0.84f * length, 0.84f * length);
        canvas.drawArc(rect, 135, 270, true, paint);

        paint.setColor(Color.WHITE);
        paint.setShader(null);
        rect = getRectF(-0.58f * length, -(length * 0.58f), 0.58f * length, 0.58f * length);
        canvas.drawArc(rect, 135, 270, true, paint);

        //白色区域灰色描边
        paint.setColor(color_636363);
        paint.setShader(null);
        rect = getRectF(-0.56f * length, -(length * 0.56f), 0.56f * length, 0.56f * length);
        canvas.drawArc(rect, 180, 360, true, paint);

        //白色区域灰色描边
        paint.setColor(backGroundColor);
        paint.setShader(null);
        rect = getRectF(-0.54f * length, -(length * 0.54f), 0.54f * length, 0.54f * length);
        canvas.drawArc(rect, 180, 360, true, paint);

        //白色区域灰色描边
        paint.setColor(color_636363);
        paint.setShader(null);
        rect = getRectF(-0.44f * length, -(length * 0.44f), 0.44f * length, 0.44f * length);
        canvas.drawArc(rect, 180, 360, true, paint);

        //白色区域灰色描边
        paint.setColor(backGroundColor);
        paint.setShader(null);
        rect = getRectF(-0.42f * length, -(length * 0.42f), 0.42f * length, 0.42f * length);
        canvas.drawArc(rect, 180, 360, true, paint);

        //白色区域黑色色描边
        paint.setColor(color_393939);
        paint.setShader(null);
        rect = getRectF(-0.40f * length, -(length * 0.40f), 0.40f * length, 0.40f * length);
        canvas.drawArc(rect, 180, 360, true, paint);

        //气压刻度线
        if (isDrawerLine) {
            initMarkLine(canvas);
        }
        //指针
        initPointer(canvas);

        //白色区域蓝色描边
        canvas.restore();
        canvas.save();
        canvas.translate(canvas.getWidth() / 2, r);
        canvas.rotate(rotate, 0f, 0f);

        paint.setShader(rotateGradient);
        rect = getRectF(-0.36f * length, -(length * 0.36f), 0.36f * length, 0.36f * length);
        canvas.drawArc(rect, 180, 360, true, paint);

        canvas.restore();
        canvas.save();
        canvas.translate(canvas.getWidth() / 2, r);
        //白色区域灰色描边#B2D2EC
        RadialGradient radialGradient = new RadialGradient(0, 0, length, color_1aACCEE9,
                color_ACCEE9, Shader.TileMode.CLAMP);
        paint.setShader(radialGradient);
        rect = getRectF(-0.32f * length, -(length * 0.32f), 0.32f * length, 0.32f * length);
        canvas.drawArc(rect, 180, 360, true, paint);

        //内部白色区域
        paint.setColor(Color.WHITE);
        paint.setShader(null);
        rect = getRectF(-0.28f * length, -(length * 0.28f), 0.28f * length, 0.28f * length);
        canvas.drawArc(rect, 180, 360, true, paint);
    }

    /**
     * Desc:获取矩阵
     * <p>
     * Author: [李豫]
     * Date: 2020-09-01
     *
     * @return rect f
     */
    private RectF getRectF(float left, float top, float right, float bottom) {
        if (rect == null) {
            rect = new RectF();
        }
        rect.left = left;
        rect.top = top;
        rect.right = right;
        rect.bottom = bottom;
        return rect;
    }

    /**
     * Desc:设置进度条
     * <p>
     * Author: [李豫]
     * Date: 2020-09-05
     *
     * @param per
     */
    public void setProgress(float per) {
        if (!isTouching) {
            isDrawerLine = true;
            float perOld = this.per;
            this.per = per;
            this.destPer = per;
            ValueAnimator va = ValueAnimator.ofFloat(perOld, per);
            va.setDuration(1000);
            va.setInterpolator(new OvershootInterpolator());
            va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    if (!isTouching) {
                        perPoint = (float) animation.getAnimatedValue();
                        invalidate();
                    }
                }
            });
            va.start();
        }
    }

    /**
     * Desc:更新进度条
     * <p>
     * Author: [李豫]
     * Date: 2020-09-05
     *
     * @param per
     */
    public void updateProgress(float per) {
        if (!isTouching) {
            float perOld = this.per;
            this.per = per;
            ValueAnimator va = ValueAnimator.ofFloat(perOld, per);
            va.setDuration(1000);
            va.setInterpolator(new OvershootInterpolator());
            va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    if (!isTouching) {
                        perPoint = (float) animation.getAnimatedValue();
                        invalidate();
                    }
                }
            });
            va.start();
        }
    }

    /**
     * Desc:开始充气动效
     * <p>
     * Author: [李豫]
     * Date: 2020-09-09
     */
    public void startRotateAnim() {
        int[] colors = {ring_second_bg, ring_bg};
        float[] positions = {0.1f, 0.9f};
        rotateGradient = new SweepGradient(0, 0, colors, positions);
        if (mHandler != null) {
            mHandler.removeCallbacks(mRotateRunnable);
            mHandler.post(mRotateRunnable);
        }
    }

    /**
     * Desc:停止充气动效
     * <p>
     * Author: [李豫]
     * Date: 2020-09-09
     */
    public void stopRotateAnim() {
        int[] colors = {ring_second_bg, ring_second_bg};
        float[] positions = {0.1f, 0.9f};
        rotateGradient = new SweepGradient(0, 0, colors, positions);
        if (mHandler != null) {
            mHandler.removeCallbacks(mRotateRunnable);
        }
        invalidate();
    }

    private Runnable mRotateRunnable = new Runnable() {
        @Override
        public void run() {
            rotate += 10;
            postInvalidate();
            mHandler.postDelayed(this, DELAY_TIME);
        }
    };

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (!isEnableTouch()) {
            return super.onTouchEvent(ev);
        }
        int action = ev.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN: {
                final int pointerIndex = ev.getActionIndex();
                final float x = ev.getX(pointerIndex);
                float y = ev.getY(pointerIndex);

                isTouching = isTouchInner(x, y);
                mLastX = x;
                mActivePointerId = ev.getPointerId(0);
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
                final float x = ev.getX(pointerIndex);
                float y = ev.getY(pointerIndex);
                dx = x - mLastX;
                mLastX = x;
                if (isTouching) {
                    doMove(dx, x, y);
                }
                break;
            }
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mActivePointerId = MotionEvent.INVALID_POINTER_ID;
//                if (isMoving) {//手指移动，才重置音乐播放
//                    isMoving = false;
//                    resetMusicPlay();
//                }
//                setProgress(per);
                if (isTouching) {
                    isTouching = false;
                    if (mCompressViewListener != null) {
                        mCompressViewListener.onAdjustCompress(perPoint);
                    }
                }
                break;
            case MotionEvent.ACTION_POINTER_DOWN: {
                final int pointerIndex = ev.getActionIndex();
                final int pointerId = ev.getPointerId(pointerIndex);
                if (pointerId != mActivePointerId) {
                    mLastX = ev.getX(pointerIndex);
                    mActivePointerId = ev.getPointerId(pointerIndex);
                }
                break;
            }
            case MotionEvent.ACTION_POINTER_UP: {
                final int pointerIndex = ev.getActionIndex();
                final int pointerId = ev.getPointerId(pointerIndex);
                if (pointerId == mActivePointerId) {
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    mLastX = ev.getX(newPointerIndex);
                    mActivePointerId = ev.getPointerId(newPointerIndex);
                }
                break;
            }
            default:
                break;
        }

        return true;
    }

    private boolean isTouchInner(float x, float y) {
        if (Math.abs(mWidth / 2 - x) <= 0.16 * mWidth / 2 && Math.abs(mHeight / 2 - y) <= 0.16 * mHeight / 2) {
            //如果触碰圆心内部区域直接返回
            return false;
        }

        if (Math.abs(mWidth / 2 - x) > length || Math.abs(mHeight / 2 - y) > length) {
            //大于表盘外围返回
            return false;
        }

        double atan = Math.atan((mHeight / 2 - y) / (x - mWidth / 2));
        double degrees = Math.toDegrees(atan);

        double realDegree = 0;
        if (x <= mWidth / 2 && y >= mHeight / 2) {
            realDegree = 40 - degrees;
        } else if (x <= mWidth / 2 && y < mHeight / 2) {
            realDegree = -(degrees - 40);
        } else if (x > mWidth / 2 && y >= mHeight / 2) {
            realDegree = 130 + (90 - degrees);
        } else if (x > mWidth / 2 && y < mHeight / 2) {
            realDegree = 220 - degrees;
        }

        if (realDegree <= 0) {
            realDegree = 0;
        }
        float point = (float) (realDegree / 260);

        if (Math.abs(point - perPoint) <= 0.1) {
            return true;
        }

        return false;
    }


    private void doMove(float dx, float x, float y) {
        if (Math.abs(mWidth / 2 - x) <= 0.16 * mWidth / 2 && Math.abs(mHeight / 2 - y) <= 0.16 * mHeight / 2) {
            //如果触碰圆心内部区域直接返回
            return;
        }

        if (Math.abs(mWidth / 2 - x) > length || Math.abs(mHeight / 2 - y) > length) {
            //大于表盘外围返回
            return;
        }

        isDrawerLine = true;

        double atan = Math.atan((mHeight / 2 - y) / (x - mWidth / 2));
        double degrees = Math.toDegrees(atan);

        double realDegree = 0;
        if (x <= mWidth / 2 && y >= mHeight / 2) {
            realDegree = 40 - degrees;
        } else if (x <= mWidth / 2 && y < mHeight / 2) {
            realDegree = -(degrees - 40);
        } else if (x > mWidth / 2 && y >= mHeight / 2) {
            realDegree = 130 + (90 - degrees);
        } else if (x > mWidth / 2 && y < mHeight / 2) {
            realDegree = 220 - degrees;
        }

        if (realDegree <= 0) {
            realDegree = 0;
        }
        perPoint = (float) (realDegree / 260);
        destPer = perPoint;
        invalidate();

//        cgangePer();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();

        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
        }
    }

    private CompressViewListener mCompressViewListener;

    public void setCompressViewListener(CompressViewListener listener) {
        this.mCompressViewListener = listener;
    }

    public interface CompressViewListener {
        void getCompressValue(float percent);

        void onAdjustCompress(float value);
    }
}